iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
自我挑戰組

打造一個糖尿病自我監測小工具:從0開始學前端系列 第 19

Day19打造一個糖尿病自我監測小工具:從0開始學前端

  • 分享至 

  • xImage
  •  

今天重點放在個人資料頁面 pofile.html ,從帳號管理頁面,點擊「編輯個人資料」能轉跳到這,我打算這邊可以修改個人的詳細資料。

先整理一下想法:

  1. 在 account.html 點「編輯個人資料」會跳到 profile.html
  2. profile.html 可以編輯並儲存個人資料。
  3. account.html 顯示的個人資料,是從 profile.html 儲存的資料(例如 localStorage 取得),所以 profile.html 修改後,account.html 也會同步顯示最新資料。

實作

profile.html

  • 其中性別是:下拉式選單
  • 糖尿病類型為 radio選項,選擇其它時,會出現隱藏式填寫框
<head>
    <title>詳細個人資料</title>
    <link rel="stylesheet" href="style.css" />
</head>

<body>
    <header>
        <h1>詳細個人資料</h1>
        <nav id="navbar">
            <a href="index.html">首頁</a>
            <a href="record.html">填寫</a>
            <a href="report.html">紀錄</a>
            <a href="account.html">帳號管理</a>
        </nav>
    </header>

    <form id="profileForm">
        <!-- 基本資料 -->
        <label for="name">姓名:</label>
        <input type="text" id="name" name="name" required>

        <label for="email">電子郵件:</label>
        <input type="email" id="email" name="email" required>

        <label for="phone">電話:</label>
        <input type="tel" id="phone" name="phone" required>

        <label for="birth">生日:</label>
        <input type="date" id="birth" name="birth" required>

        <label for="gender">性別:</label>
        <select id="gender" name="gender" required>
            <option value="">請選擇</option>
            <option value="男">男</option>
            <option value="女">女</option>
            <option value="其他">其他</option> 
        </select>

        <!-- 糖尿病相關 -->
        <label for="diabetesType">糖尿病類型:</label>
        <label><input type="radio" name="diabetesType" value="第一型" required> 第一型</label>
        <label><input type="radio" name="diabetesType" value="第二型"> 第二型</label>
        <label><input type="radio" name="diabetesType" value="妊娠型"> 妊娠型</label>
        <label><input type="radio" name="diabetesType" value="其他"> 其他</label>
        <input type="text" id="diabetesTypeOther" name="diabetesTypeOther" 
            placeholder="請填寫其他類型" style="display:none; margin-left:10px;">

        <label for="treatment">目前治療方式:</label>
        <input type="text" id="treatment" name="treatment" required>

        <label for="diagnosisDate">確診糖尿病時間:</label>
        <input type="date" id="diagnosisDate" name="diagnosisDate" required>

        <label for="familyHistory">家族病史:</label>
        <select id="familyHistory" name="familyHistory" required>
            <option value="">請選擇</option>
            <option value="有">有</option>
            <option value="沒有">沒有</option> 
        </select>

        <button type="submit">儲存資料</button>

    </form>

    <script src="script.js" defer></script>

</body>

JS 邏輯

分為三部分邏輯:

  1. 編輯資料按鈕:從 account.htmlprofile.html
  2. account.html 個人資料部分,會從 profile.html 抓表單資料
  3. profile.html 表單邏輯,按下送出後會再確認一次,正確的話回到 account.html
  4. 如果已經填過資料 → 點進去會直接帶入
  5. 如果還沒填過資料 → 會說
// ================== account.html 載入個人資料 ==================
  if (document.getElementById("nameDisplay")) {
    const data = JSON.parse(localStorage.getItem("userProfile") || "{}");

    if (data.name) {
      document.getElementById("nameDisplay").textContent = "姓名: " + data.name;
      document.getElementById("emailDisplay").textContent = "電子郵件: " + data.email;
      document.getElementById("phoneDisplay").textContent = "電話: " + data.phone;
      document.getElementById("birthDisplay").textContent = "生日: " + data.birth;
      document.getElementById("genderDisplay").textContent = "性別: " + data.gender;
      document.getElementById("diabetesTypeDisplay").textContent = "糖尿病類型: " + data.diabetesType;
      document.getElementById("treatmentDisplay").textContent = "目前治療方式: " + data.treatment;
      document.getElementById("diagnosisDateDisplay").textContent = "確診糖尿病時間: " + data.diagnosisDate;
      document.getElementById("familyHistoryDisplay").textContent = "家族病史: " + data.familyHistory;
    }

    // 編輯按鈕
    const profileBtn = document.getElementById("profileBtn");
    if (profileBtn) {
      profileBtn.addEventListener("click", function () {
        window.location.href = "profile.html";
      });
    }
  }

  // ================== profile.html 個人資料表單邏輯 ==================
const profileForm = document.getElementById("profileForm");
if (profileForm) {
  const diabetesTypeOtherInput = document.getElementById('diabetesTypeOther');

  // 頁面載入時,先隱藏 "其他" 欄位
  diabetesTypeOtherInput.style.display = 'none';
  diabetesTypeOtherInput.required = false;

  // 載入 localStorage 已存的資料
  const userProfile = JSON.parse(localStorage.getItem("userProfile") || "{}");
  if (userProfile) {
    if (userProfile.name) profileForm.name.value = userProfile.name;
    if (userProfile.email) profileForm.email.value = userProfile.email;
    if (userProfile.phone) profileForm.phone.value = userProfile.phone;
    if (userProfile.birth) profileForm.birth.value = userProfile.birth;
    if (userProfile.gender) profileForm.gender.value = userProfile.gender;
    if (userProfile.treatment) profileForm.treatment.value = userProfile.treatment;
    if (userProfile.diagnosisDate) profileForm.diagnosisDate.value = userProfile.diagnosisDate;
    if (userProfile.familyHistory) profileForm.familyHistory.value = userProfile.familyHistory;

    // 處理糖尿病類型
    if (userProfile.diabetesType) {
      const radios = profileForm.querySelectorAll('input[name="diabetesType"]');
      let matched = false;
      radios.forEach(radio => {
        if (radio.value === userProfile.diabetesType) {
          radio.checked = true;
          matched = true;
        }
      });
      if (!matched) {
        profileForm.querySelector('input[value="其他"]').checked = true;
        diabetesTypeOtherInput.style.display = 'inline-block';
        diabetesTypeOtherInput.value = userProfile.diabetesType;
        diabetesTypeOtherInput.required = true;
      }
    }
  }

  // 監聽糖尿病類型的切換
  profileForm.querySelectorAll('input[name="diabetesType"]').forEach(radio => {
    radio.addEventListener('change', function() {
      if (this.value === '其他') {
        diabetesTypeOtherInput.style.display = 'inline-block';
        diabetesTypeOtherInput.required = true;
      } else {
        diabetesTypeOtherInput.style.display = 'none';
        diabetesTypeOtherInput.required = false;
        diabetesTypeOtherInput.value = '';
      }
    });
  });

  // 表單送出 → 自訂確認視窗
  profileForm.addEventListener("submit", function(e) {
    e.preventDefault();
    const formData = new FormData(profileForm);
    let diabetesType = formData.get("diabetesType");
    if (diabetesType === "其他") {
      diabetesType = formData.get("diabetesTypeOther") || "其他";
    }

    const newProfile = {
      name: formData.get("name"),
      email: formData.get("email"),
      phone: formData.get("phone"),
      birth: formData.get("birth"),
      gender: formData.get("gender"),
      diabetesType: diabetesType,
      treatment: formData.get("treatment"),
      diagnosisDate: formData.get("diagnosisDate"),
      familyHistory: formData.get("familyHistory")
    };

    // 建立自訂確認視窗
    const overlay = document.createElement("div");
    overlay.style.cssText = `
      position: fixed; top:0; left:0; width:100vw; height:100vh;
      background: rgba(0,0,0,0.4); display:flex; align-items:center; justify-content:center; z-index:9999;`;

    const box = document.createElement("div");
    box.style.cssText = `
      background:#fff; border-radius:8px; padding:30px 24px 16px 24px;
      min-width:320px; max-width:90vw; box-shadow:0 2px 12px rgba(0,0,0,0.18);`;

    box.innerHTML = `
      <h3 style="margin-top:0;">請確認您的資料</h3>
      <div style="text-align:left; font-size:1em; margin-bottom:18px;">
        <p><b>姓名:</b>${newProfile.name}</p>
        <p><b>電子郵件:</b>${newProfile.email}</p>
        <p><b>電話:</b>${newProfile.phone}</p>
        <p><b>生日:</b>${newProfile.birth}</p>
        <p><b>性別:</b>${newProfile.gender}</p>
        <p><b>糖尿病類型:</b>${newProfile.diabetesType}</p>
        <p><b>目前治療方式:</b>${newProfile.treatment}</p>
        <p><b>確診糖尿病時間:</b>${newProfile.diagnosisDate}</p>
        <p><b>家族病史:</b>${newProfile.familyHistory}</p>
      </div>
      <div style="display:flex; justify-content:space-between; margin-top:18px;">
        <button id="cancelProfileConfirm" style="padding:8px 18px; background:#ccc; color:#333; border:none; border-radius:4px;">取消</button>
        <button id="okProfileConfirm" style="padding:8px 18px; background:#4CAF50; color:#fff; border:none; border-radius:4px;">確認送出</button>
      </div>
    `;
    overlay.appendChild(box);
    document.body.appendChild(overlay);

    document.getElementById("cancelProfileConfirm").onclick = () => {
      document.body.removeChild(overlay);
    };
    document.getElementById("okProfileConfirm").onclick = () => {
      localStorage.setItem("userProfile", JSON.stringify(newProfile));
      document.body.removeChild(overlay);
      window.location.href = "account.html";
    };
  });
}

今天大概完成了,明天會放上成果圖片。


上一篇
Day18打造一個糖尿病自我監測小工具:從0開始學前端
下一篇
Day20打造一個糖尿病自我監測小工具:從0開始學前端
系列文
打造一個糖尿病自我監測小工具:從0開始學前端23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言